home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / dosrcss.zip / RCSGEN.C < prev    next >
C/C++ Source or Header  |  1990-07-18  |  13KB  |  345 lines

  1. /*
  2.  *                     RCS revision generation
  3.  */
  4. #ifndef lint
  5. static char rcsid[]= "$Id: rcsgen.c,v 5.2 90/07/15 11:33:58 ROOT_DOS Release $ Purdue CS";
  6. #endif
  7.  
  8. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  9.    Distributed under license by the Free Software Foundation, Inc.
  10.  
  11. This file is part of RCS.
  12.  
  13. RCS is free software; you can redistribute it and/or modify
  14. it under the terms of the GNU General Public License as published by
  15. the Free Software Foundation; either version 1, or (at your option)
  16. any later version.
  17.  
  18. RCS is distributed in the hope that it will be useful,
  19. but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. GNU General Public License for more details.
  22.  
  23. You should have received a copy of the GNU General Public License
  24. along with RCS; see the file COPYING.  If not, write to
  25. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  
  27. Report problems and direct all questions to:
  28.  
  29.     rcs-bugs@cs.purdue.edu
  30.  
  31. */
  32.  
  33.  
  34.  
  35. /* $Log:    rcsgen.c,v $
  36.  * Revision 5.2  90/07/15  11:33:58  ROOT_DOS
  37.  * DOS version of RCS 4.0 checked in for MODS
  38.  * by lfk@athena.mit.edu
  39.  * Also update to MSC 6.0
  40.  * 
  41.  * Revision 4.7  89/05/01  15:12:49  narten
  42.  * changed copyright header to reflect current distribution rules
  43.  * 
  44.  * Revision 4.6  88/11/08  12:01:13  narten
  45.  * changes from  eggert@sm.unisys.com (Paul Eggert)
  46.  * 
  47.  * Revision 4.6  88/08/28  14:59:10  eggert
  48.  * Shrink stdio code size; allow cc -R; remove lint; isatty() -> ttystdin()
  49.  * 
  50.  * Revision 4.5  87/12/18  11:43:25  narten
  51.  * additional lint cleanups, and a bug fix from the 4.3BSD version that
  52.  * keeps "ci" from sticking a '\377' into the description if you run it
  53.  * with a zero-length file as the description. (Guy Harris)
  54.  * 
  55.  * Revision 4.4  87/10/18  10:35:10  narten
  56.  * Updating version numbers. Changes relative to 1.1 actually relative to
  57.  * 4.2
  58.  * 
  59.  * Revision 1.3  87/09/24  13:59:51  narten
  60.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  61.  * warnings)
  62.  * 
  63.  * Revision 1.2  87/03/27  14:22:27  jenkins
  64.  * Port to suns
  65.  * 
  66.  * Revision 1.1  84/01/23  14:50:28  kcs
  67.  * Initial revision
  68.  * 
  69.  * Revision 4.2  83/12/02  23:01:39  wft
  70.  * merged 4.1 and 3.3.1.1 (clearerr(stdin)).
  71.  * 
  72.  * Revision 4.1  83/05/10  16:03:33  wft
  73.  * Changed putamin() to abort if trying to reread redirected stdin.
  74.  * Fixed getdesc() to output a prompt on initial newline.
  75.  * 
  76.  * Revision 3.3.1.1  83/10/19  04:21:51  lepreau
  77.  * Added clearerr(stdin) for re-reading description from stdin.
  78.  * 
  79.  * Revision 3.3  82/11/28  21:36:49  wft
  80.  * 4.2 prerelease
  81.  * 
  82.  * Revision 3.3  82/11/28  21:36:49  wft
  83.  * Replaced ferror() followed by fclose() with ffclose().
  84.  * Putdesc() now suppresses the prompts if stdin
  85.  * is not a terminal. A pointer to the current log message is now
  86.  * inserted into the corresponding delta, rather than leaving it in a
  87.  * global variable.
  88.  *
  89.  * Revision 3.2  82/10/18  21:11:26  wft
  90.  * I added checks for write errors during editing, and improved
  91.  * the prompt on putdesc().
  92.  *
  93.  * Revision 3.1  82/10/13  15:55:09  wft
  94.  * corrected type of variables assigned to by getc (char --> int)
  95.  */
  96.  
  97.  
  98.  
  99.  
  100. #include "rcsbase.h"
  101.  
  102. extern struct hshentry * getnum();
  103. extern FILE * fopen();
  104. extern savestring();
  105. extern editstring();
  106.  
  107. extern int nextc;          /* next character from lexical analyzer          */
  108. extern char Ktext[];       /* keywords from syntax analyzer                 */
  109. extern char Klog[];        /* Keyword "log"                                 */
  110. extern char Kdesc[];       /* Keyword for description                       */
  111. extern FILE * frewrite;    /* new RCS file                                  */
  112. extern FILE * fcopy;       /* result file during editing                    */
  113. extern char * resultfile;  /* file name for fcopy                           */
  114. extern int    rewriteflag; /* indicates whether to rewrite the input file   */
  115. #ifdef MSDOS
  116. extern char tmpdir[NCPPN];
  117. #endif /* MSDOS */
  118.  
  119. char    curlogmsg[logsize]; /* buffer for current log message                */
  120.  
  121. enum stringwork {copy, edit, expand, edit_expand };
  122. /* parameter to scandeltatext() */
  123.  
  124.  
  125.  
  126.  
  127. char * buildrevision(deltas, target, dir, expandflag)
  128. struct hshentry ** deltas, * target;
  129. char * dir; int expandflag;
  130. /* Function: Generates the revision given by target
  131.  * by retrieving all deltas given by parameter deltas and combining them.
  132.  * If dir==nil, the revision is printed on the standard output,
  133.  * otherwise written into a temporary file in directory dir.
  134.  * if expandflag==true, keyword expansion is performed.
  135.  * returns false on errors, the name of the file with the revision otherwise.
  136.  *
  137.  * Algorithm: Copy inital revision unchanged. Then edit all revisions but
  138.  * the last one into it, alternating input and output files (resultfile and
  139.  * editfile). The last revision is then edited in, performing simultaneous
  140.  * keyword substitution (this saves one extra pass).
  141.  * All this simplifies if only one revision needs to be generated,
  142.  * or no keyword expansion is necessary, or if output goes to stdout.
  143.  */
  144. {
  145.         int i;
  146.  
  147.         if (deltas[0]==target) {
  148.                 /* only latest revision to generate */
  149.                 if (dir==nil) {/* print directly to stdout */
  150.                         fcopy=stdout;
  151.                         scandeltatext(target,expand);
  152.                         return(char *) true;
  153.                 } else {
  154.                         initeditfiles(dir);
  155.                         scandeltatext(target,expandflag?expand:copy);
  156.                         ffclose(fcopy);
  157.                         return(resultfile);
  158.                 }
  159.         } else {
  160.                 /* several revisions to generate */
  161. #ifdef MSDOS
  162.                 initeditfiles(dir?dir: tmpdir);
  163. #else
  164.                 initeditfiles(dir?dir:"/tmp/");
  165. #endif /* MSDOS */
  166.                 /* write initial revision into fcopy, no keyword expansion */
  167.                 scandeltatext(deltas[0],copy);
  168.                 i = 1;
  169.                 while (deltas[i+1] != nil) {
  170.                         /* do all deltas except last one */
  171.                         scandeltatext(deltas[i++],edit);
  172.                 }
  173.                 if (!expandflag) {
  174.                         /* no keyword expansion; only invoked from ci */
  175.                         scandeltatext(deltas[i],edit);
  176.                         finishedit((struct hshentry *)nil);
  177.                         ffclose(fcopy);
  178.                 } else {
  179.                         /* perform keyword expansion*/
  180.                         /* first, get to beginning of file*/
  181.                         finishedit((struct hshentry *)nil); swapeditfiles(dir==nil);
  182.                         scandeltatext(deltas[i],edit_expand);
  183.                         finishedit(deltas[i]);
  184.                         if (dir!=nil) ffclose(fcopy);
  185.                 }
  186.                 return(resultfile); /*doesn't matter for dir==nil*/
  187.         }
  188. }
  189.  
  190.  
  191.  
  192. scandeltatext(delta,func)
  193. struct hshentry * delta; enum stringwork func;
  194. /* Function: Scans delta text nodes up to and including the one given
  195.  * by delta. For the one given by delta, the log message is saved into
  196.  * curlogmsg and the text is processed according to parameter func.
  197.  * Assumes the initial lexeme must be read in first.
  198.  * Does not advance nexttok after it is finished.
  199.  */
  200. {       struct hshentry * nextdelta;
  201.  
  202.         do {
  203.                 nextlex();
  204.                 if (!(nextdelta=getnum())) {
  205.                         fatserror("Can't find delta for revision %s", delta->num);
  206.                 }
  207.                 if (!getkey(Klog) || nexttok!=STRING)
  208.                         serror("Missing log entry");
  209.                 elsif (delta==nextdelta) {
  210.                         VOID savestring(curlogmsg,logsize);
  211.                         delta->log=curlogmsg;
  212.                 } else {readstring();
  213.                         delta->log= "";
  214.                 }
  215.                 nextlex();
  216.                 if (!getkey(Ktext) || nexttok!=STRING)
  217.                         fatserror("Missing delta text");
  218.  
  219.                 if(delta==nextdelta)
  220.                         /* got the one we're looking for */
  221.                         switch (func) {
  222.                         case copy:      copystring();
  223.                                         break;
  224.                         case expand:    xpandstring(delta);
  225.                                         break;
  226.                         case edit:      editstring((struct hshentry *)nil);
  227.                                         break;
  228.                         case edit_expand: editstring(delta);
  229.                                         break;
  230.                         }
  231.                 else    readstring(); /* skip over it */
  232.  
  233.         } while (delta!=nextdelta);
  234. }
  235.  
  236.  
  237. int stdinread; /* stdinread>0 if redirected stdin has been read once */
  238.  
  239. int ttystdin()
  240. {
  241.     static int initialized, istty;
  242.     if (!initialized) {
  243.         istty = isatty(fileno(stdin));
  244.         initialized = 1;
  245.     }
  246.     return istty;
  247. }
  248.  
  249. putdesc(initflag,textflag,textfile,quietflag)
  250. int initflag,textflag; char * textfile; int quietflag;
  251. /* Function: puts the descriptive text into file frewrite.
  252.  * if !initflag && !textflag, the text is copied from the old description.
  253.  * Otherwise, if the textfile!=nil, the text is read from that
  254.  * file, or from stdin, if textfile==nil.
  255.  * Increments stdinread if text is read from redirected stdin.
  256.  * if initflag&&quietflag&&!textflag, an empty text is inserted.
  257.  * if !initflag, the old descriptive text is discarded.
  258.  */
  259. {       register FILE * txt; register int c, old1, old2;
  260.     register FILE * frew;
  261. #ifdef lint
  262.     if (quietflag ==  0) initflag = quietflag; /* silencelint */
  263. #endif
  264.  
  265.     frew = frewrite;
  266.         if (!initflag && !textflag) {
  267.                 /* copy old description */
  268.                 VOID fprintf(frew,"\n\n%s%c",Kdesc,nextc);
  269.                 rewriteflag=true; getdesc(false);
  270.         } else {
  271.                 /* get new description */
  272.                if (!initflag) {
  273.                         /*skip old description*/
  274.                         rewriteflag=false; getdesc(false);
  275.                 }
  276.                 VOID fprintf(frew,"\n\n%s\n%c",Kdesc,SDELIM);
  277.                 if (textfile) {
  278.                         old1='\n';
  279.                         /* copy textfile */
  280.                         if ((txt=fopen(textfile,"r"))!=NULL) {
  281.                                 while ((c=getc(txt))!=EOF) {
  282.                                         if (c==SDELIM) VOID putc(c,frew); /*double up*/
  283.                                         VOID putc(c,frew);
  284.                                         old1=c;
  285.                                 }
  286.                                 if (old1!='\n') VOID putc('\n',frew);
  287.                                 VOID fclose(txt);
  288.                 VOID putc(SDELIM,frew);
  289.                 VOID fputs("\n\n", frew);
  290.                 return;
  291.                         } else {
  292.                                 error("Can't open file %s with description",textfile);
  293.                                 if (!ttystdin()) return;
  294.                                 /* otherwise, get description from terminal */
  295.                         }
  296.                 }
  297.                 /* read text from stdin */
  298.                 if (ttystdin()) {
  299. #ifdef MSDOS
  300.                     VOID fputs("enter description, terminated with ^Z or '.':\n",stderr);
  301. #else
  302.                     VOID fputs("enter description, terminated with ^D or '.':\n",stderr);
  303. #endif /* MSDOS */
  304.                     VOID fputs("NOTE: This is NOT the log message!\n>> ",stderr);
  305.             if (feof(stdin))
  306.                     clearerr(stdin);
  307.                 } else {  /* redirected stdin */
  308.                     if (stdinread>0)
  309.                         faterror("Can't reread redirected stdin for description; use -t<file>");
  310.                     stdinread++;
  311.                 }
  312.                 c = '\0'; old2= '\n';
  313.                 if ((old1=getchar())==EOF) {
  314.                         if (ttystdin()) {
  315.                              VOID putc('\n',stderr);
  316.                              clearerr(stdin);
  317.             }
  318.         } else {
  319.              if (old1=='\n' && ttystdin())
  320.              VOID fputs(">> ",stderr);
  321.              for (;;) {
  322.                             c=getchar();
  323.                             if (c==EOF) {
  324.                                     if (ttystdin()) {
  325.                                             VOID putc('\n',stderr);
  326.                                             clearerr(stdin);
  327.                     }
  328.                                     VOID putc(old1,frew);
  329.                                     if (old1!='\n') VOID putc('\n',frew);
  330.                                     break;
  331.                             }
  332.                             if (c=='\n' && old1=='.' && old2=='\n') {
  333.                                     break;
  334.                             }
  335.                             if (c=='\n' && ttystdin()) VOID fputs(">> ",stderr);
  336.                 if(old1==SDELIM) VOID putc(old1,frew); /* double up*/
  337.                 VOID putc(old1,frew);
  338.                             old2=old1;
  339.                             old1=c;
  340.                     } /* end for */
  341.         }
  342.         VOID putc(SDELIM,frew); VOID fputs("\n\n",frew);
  343.         }
  344. }
  345.